String clazzTpl({package}) => """
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:$package/utils/print_util.dart';

/// Generates Dart code
class LogInterceptors extends InterceptorsWrapper {
  static const String timeKey = "HttpRequestTime";
  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    // 记录请求时间 毫秒
    options.extra[timeKey] = DateTime.now().millisecondsSinceEpoch;
    Map<String, dynamic> header = {
      'host': options.baseUrl,
      'url': options.path,
    };
    if (options.headers.isNotEmpty) {
      header['headers'] = options.headers;
    }
    if (options.queryParameters.isNotEmpty) {
      header['queryParams'] = options.queryParameters;
    }
    if (options.data != null) {
      if (options.data is FormData) {
        header['body'] = "FormData [\${options.data.toString()}]";
      } else {
        header['body'] = options.data;
      }
    }
    logDebugPrint(LogInterceptors.formatJson(
      jsonEncode(header),
      tag: 'request',
      isJsonString: true,
      // prefix: ["url:" + options.baseUrl, "path:" + options.path],
    ));
    handler.next(options);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) async {
    // 记录请求时间 毫秒
    int time = DateTime.now().millisecondsSinceEpoch -
        (response.requestOptions.extra[timeKey] as int);
    logDebugPrint(LogInterceptors.formatJson(
      response.toString(),
      tag: 'response',
      isJsonString: true,
      prefix: [
        "url:\${response.requestOptions.baseUrl}",
        "path:\${response.requestOptions.path}",
        "time:\${(time / 1000).toStringAsFixed(2)}秒",
      ],
    ));
    handler.next(response);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) async {
    var error = {
      'err': err.toString(),
      'request': err.requestOptions.toString(),
      'response': err.response.toString(),
    };
    logDebugPrint(LogInterceptors.formatJson(
      error.toString(),
      tag: 'error',
      isJsonString: false,
      prefix: [
        "url:\${err.requestOptions.baseUrl}",
        "path:\${err.requestOptions.path}"
      ],
    ));
    handler.next(err);
  }

  static String? formatJson(String json,
      {String tag = 'xxxx', bool isJsonString = true, List<String>? prefix}) {
    if (json.isEmpty || !kDebugMode) return null;
    StringBuffer sb = StringBuffer();
    int lengthW = 80;
    for (int i = 0; i < lengthW; i++) {
      if (i == 0) sb.write('╔');
      sb.write('═');
    }
    sb.write('\\n');
    sb.write('║ TAG:\$tag');
    if (prefix != null) {
      sb.write('\\n');
      sb.write('║ ');
      for (var element in prefix) {
        sb.write('\\n║ \$element');
      }
      sb.write('\\n');
      sb.write('║ ');
    }
    sb.write('\\n');
    String last = '';
    String current = '';
    int indent = 0;
    for (int i = 0; i < json.length; i++) {
      last = current;
      current = json[i];
      switch (current) {
        case '{':
        case '[':
          if (i == 0) sb.write('║ ');
          sb.write(current);
          sb.write('\\n');
          indent++;
          _indent(sb, indent);
          break;
        case '}':
        case ']':
          sb.write('\\n');
          if (i == json.length - 1) {
            sb.write('║ ');
          }
          indent--;
          _indent(sb, indent);
          sb.write(current);
          break;
        case ',':
          sb.write(current);
          if (isJsonString) {
            if (last != '' && (json[i + 1] == '"' || json[i + 1] == '{')) {
              sb.write('\\n');
              _indent(sb, indent);
            }
          } else {
            if (last != '') {
              sb.write('\\n');
              _indent(sb, indent);
            }
          }
          break;
        default:
          sb.write(current);
      }
    }
    sb.write('\\n');
    for (int i = 0; i < lengthW; i++) {
      if (i == 0) sb.write('╚');
      sb.write('═');
    }
    return sb.toString();
  }

  static void _indent(StringBuffer sb, int number) {
    for (int i = 0; i < number; i++) {
      if (i == 0) sb.write('║ ');
      sb.write('\\t');
    }
  }
}
""";
